__author__ = 'Administrator'

import numpy as np
import matplotlib.pyplot as plt

def loadDataSet(filename):
    '''
        从文档中加载数据
        filename:文件名
    '''
    fr = open(filename)
    xArray = []
    yArray=[]
    for line in fr.readlines():
        sps = line.split("\t")
        features=[]
        for i in range(len(sps) - 1):
            features.append(float(sps[i]))
        xArray.append(features)
        yArray.append(float(sps[-1]))
    return np.array(xArray),np.array(yArray)

def standardRegression(xArray,yArray):
    '''
        标准回归，用最小二乘法
        w=(X^T X)^-1 X^T Y          X^T:X的转置。X^-1: X的逆
    '''
    xMat = np.mat(xArray)
    yMat = np.mat(yArray).T

    x = xMat.T * xMat
    if(np.linalg.det(x) != 0):      #np.linalg.det() 求矩阵的行列式。若为0，则说明矩阵不可逆。
        w = x.I * xMat.T * yMat
        return w
    else:
        print("矩阵不可逆！")

def weightedRegression(xArray,yArray,data2Predict,k = 0.01):
    '''
        局部加权线性回归
        通过修改k值来获取不同拟合程度的曲线。调优。
    '''
    if(k == 0):
        print('k cannot be zero!')
        return
    xMat = np.mat(xArray)
    yMat = np.mat(yArray).T
    m = xMat.shape[0]
    weighted = np.zeros((m,m))
    for j in range(m):
        differ = xMat[j,:] - data2Predict
        weighted[j,j] = np.exp(differ * differ.T / (-2.0 * k **2))
    x = xMat.T * weighted * xMat
    if np.linalg.det(x) != 0:
        return x.I * xMat.T * weighted * yMat
    else :
        print('矩阵不可逆！')

def weightedRegressionTest(xArray,yArray):
    '''
        LWLR局部加权线性回归
    '''
    m = xArray.shape[0]
    yHat = np.zeros(m)
    for i in range(m):
        w = weightedRegression(xArray,yArray,xArray[i])
        yHat[i] = xArray[i] * w

    xCopy = xArray.copy()
    hasSorted = xCopy[:,1].argsort(0)
    x = xCopy[hasSorted]
    y = yHat[hasSorted]
    plt.gcf()
    plt.plot(x[:,1].transpose(),y,'g-',lw='3.0')
    #plt.show()
    return yHat


def ridgeRegression(xArray,yArray,lam = 0.2):
    '''
        岭回归
    '''
    xMat = np.mat(xArray)
    yMat = np.mat(yArray).T

    n = xArray.shape[1]
    e = np.eye(n)

    x = xMat.T * xMat + lam * e
    if np.linalg.det(x) != 0:
        w = x.I * (xMat.T * yMat)
        return w


def paintLineOfFit(xArray,w):
    '''
        绘制拟合曲线
    '''
    xMat = np.mat(xArray)
    xMat.copy().sort(0)             #a.sort()木有返回值的。排序的是自身。而np.sort(a)有返回值。
    yHat = xMat * np.mat(w)
    plt.gcf()
    plt.plot(xMat[:,1],yHat,"r-")
    #plt.show()

def paintData(xArray,yArray):
    x = xArray[:,1].transpose()

    plt.gcf()
    plt.scatter(x,yArray)
    #plt.show()

if __name__ == '__main__':
    filename='../source/ex0.txt'
    xArray,yArray = loadDataSet(filename)
    plt.figure(1)
    paintData(xArray,yArray)
    w = standardRegression(xArray,yArray)
    paintLineOfFit(xArray,w)
    weightedRegressionTest(xArray,yArray)
    plt.show()

    plt.figure(2)
    paintData(xArray,yArray)
    w2 = ridgeRegression(xArray,yArray)
    paintLineOfFit(xArray,w2)

    plt.show()
